package netnotifier.builder;

import java.lang.reflect.Array;

import netnotifier.NetNotifier;
import netnotifier.notification.DNSPacket;
import netnotifier.notification.EthernetPacket;
import netnotifier.notification.IPv4Packet;
import netnotifier.notification.RawPacket;
import netnotifier.notification.TCPPacket;
import netnotifier.notification.UDPPacket;
import netnotifier.notification.WifiPacket;

public class PacketBuilder extends NetBuilder
{
	NetNotifier notifier=NetNotifier.instance;
	
	public PacketBuilder()
	{
		try
		{
			notifier.subscribe(Class.forName("netnotifier.notification.RawPacket"),this,"gotRawPacket");
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	
	// check what sort of device this packet came from
	// most of the time you will be getting packets from ethernet devices,
	// but wifi devices in monitor mode etc need to be handled differently
	public void gotRawPacket(Object o)
	{
		RawPacket rawPacket=(RawPacket)o;

		if(rawPacket.datalink==127)createWifiPacket(rawPacket,0);
		else createEthernetPacket(rawPacket,0);
	}
	
	public void createWifiPacket(RawPacket rawPacket, int offset)
	{
		if(rawPacket.rawData.length<58)return;
		WifiPacket wifiPacket=new WifiPacket(rawPacket.rawData,offset);
		rawPacket.contributions.add(wifiPacket);
		wifiPacket.components.add(wifiPacket);
		
		if(wifiPacket.ethertype==0x800)
		{
			if(rawPacket.rawData.length<78)return;
			createIPPacket(rawPacket,58);
		}
	}
	
	public void createEthernetPacket(RawPacket rawPacket, int offset)
	{
		EthernetPacket ethPacket=new EthernetPacket(rawPacket.rawData,offset);
		rawPacket.contributions.add(ethPacket);
		ethPacket.components.add(rawPacket);
		
		notifier.contribute(ethPacket);
		
		if(ethPacket.ethertype==0x800)
		{
			
			createIPPacket(rawPacket,14);
		}
	}
	
	public void createIPPacket(RawPacket rawPacket, int ipOffset)
	{
		IPv4Packet ipv4Packet=new IPv4Packet(rawPacket.rawData,ipOffset);
		rawPacket.contributions.add(ipv4Packet);
		ipv4Packet.components.add(rawPacket);
		notifier.contribute(ipv4Packet);
		
		if(ipv4Packet.protocol==0x01); // ICMP
		
		if(ipv4Packet.protocol==0x06) // TCP
		{
			int tcpOffset=ipOffset+ipv4Packet.headerLength;
			int tcpLength=ipv4Packet.totalLength-ipv4Packet.headerLength;
			
			TCPPacket tcpPacket=new TCPPacket(rawPacket.rawData,tcpOffset,tcpLength);
			rawPacket.contributions.add(tcpPacket);
			tcpPacket.components.add(rawPacket);
			notifier.contribute(tcpPacket);
		}
		
		try
		{
		
		if(ipv4Packet.protocol==0x11) // UDP
		{
			int udpOffset=ipOffset+ipv4Packet.headerLength;
			int udpLength=ipv4Packet.totalLength-ipv4Packet.headerLength;
			
			UDPPacket udpPacket=new UDPPacket(rawPacket.rawData,udpOffset,udpLength);
			
			ipv4Packet.contributions.add(udpPacket);
			udpPacket.components.add(ipv4Packet);
			
			notifier.contribute(udpPacket);
			
			// create a DNS packet
			if(udpPacket.type.equals("DNS"))
			{
				int dnsOffset=udpOffset+8;
				int dnsLength=udpPacket.dataLength;
				DNSPacket dnsPacket=new DNSPacket(rawPacket.rawData,dnsOffset,dnsLength);
				
				udpPacket.contributions.add(dnsPacket);
				dnsPacket.components.add(udpPacket);
				
				notifier.contribute(dnsPacket);
			}
		}
		
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		
	}
}